package com.tahado.service;

import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.JsonParser;
import com.google.gson.reflect.TypeToken;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.codec.binary.Base64;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.ByteArrayInputStream;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;
/**
 * Wrapper around signed request map
 * User: dallan
 */
public class SignedRequest {
   private Map<String,Object> data;

   public SignedRequest(JsonElement json) {
  
         data = jsonToMap(json);
   
   }

	public String getUid() {
      return (String)data.get("user_id");
   }

   @Override
public String toString() {
	return "SignedRequest [getUid()=" + getUid() + ", getOauthToken()="
			+ getOauthToken() + ", getExpires()=" + getExpires()
			+ ", getAlgorithm()=" + getAlgorithm() + "]";
}

public String getOauthToken() {
      return (String)data.get("oauth_token");
   }

   public Double getExpires() {
      return (Double)data.get("expires");
   }

   public String getAlgorithm() {
      return (String)data.get("algorithm");
   }
   
   
   
   
   /**
    * Convert json object to map
    * @param json to convert
    * @return json in map form
    * @throws com.google.gson.JsonParseException if the json object is not a map
    */
   public static Map<String,Object> jsonToMap(JsonElement json) {
      return new Gson().fromJson(json, new TypeToken<Map<String, Object>>() {}.getType());
   }
   
   /**
    * Parses a signed_request and validates the signature.
    *
    * @param signedRequestString A signed token
    * @return SignedRequest the payload inside it or null if the sig is wrong
 * @throws UnsupportedEncodingException 
    */
 public static SignedRequest parseSignedRequest(String signedRequestString, String secret) throws UnsupportedEncodingException {
    String[] fields = signedRequestString.split("\\.", 2);
    String encodedSig = fields[0];
    String payload = fields[1];
    // decode the data
 
       byte[] sig = base64UrlDecode(encodedSig);
       String decodedPayload = null;

		decodedPayload = new String(base64UrlDecode(fields[1]), "UTF-8");

		JsonElement json =new JsonParser().parse(decodedPayload);
       SignedRequest signedRequest = new SignedRequest(json);
       if (!"HMAC-SHA256".equals(signedRequest.getAlgorithm().toUpperCase())) {
          return null;
       }

       // check sig
       byte[] expectedSig = hash_hmac_sha256(payload, secret);
       if (!Arrays.equals(sig, expectedSig)) {
          return null;
       }
       return signedRequest;

  
 }
 private static  byte[] hash_hmac_sha256(String s, String apiSecret) {
     byte[] result = null;
     try {
         Mac mac = Mac.getInstance("HmacSHA256");
         SecretKeySpec secret = new SecretKeySpec(apiSecret.getBytes(),"HmacSHA256");
         mac.init(secret);
         result = mac.doFinal(s.getBytes("UTF-8"));
     } catch (Exception e) {
        throw new RuntimeException(e);
     }
     return result;
}

protected static byte[] base64UrlDecode(String s) {
     return Base64.decodeBase64(s.replace('-', '+').replace('_', '/').getBytes());
  }
}
